#include <modbus.h>
#include <modbus-tcp.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include "list.h"
#include "shmem.h"
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <unistd.h>
#include "cJSON.h"
#include "msg_queue_peer.h"
#include <math.h>
#include <sys/cdefs.h>

#define MAX_NODE 10
#define STD_NODE_LEN sizeof(struct std_node)
#define MAX_NODE_SIZE (MAX_NODE * STD_NODE_LEN)

union values {
    BOOL b_val;  //bool类型存储空间
    int i_val;   //整形值存储空间
    float f_val; //浮点值存储空间
};

struct std_node
{
    int key;              //唯一键值
    char name[32];        //设备名
    int type;             //数据点类型
    int dev_type;         //数据点属于哪个设备，根据网关支持的设备自行定义
    union values old_val; //变化上报后需要更新旧值
    union values new_val; //从共享内存取出最新数据，放到new_val中
    int ret;              //默认为-1，采集成功后设置为1，采集失败再置-1
};

static struct shm_param para;
static int *total;
static struct std_node *node_arr;

modbus_t *mod;

struct msgbuf
{
    long mtype;      //不小于0
    char mdata[256]; //存放JSON格式的信息
};

uint16_t s5[32];   //数
uint8_t data1[32]; //开/关

//上传共享内存
void *Data_get(void *arg)
{
    int ret = -1;
    ret = shm_init(&para, "shm_test", MAX_NODE_SIZE);
    if (ret < 0)
    {
        perror("shm_init error:");
    }

    void *addr = shm_getaddr(&para);
    if (addr == NULL)
    {
        perror("shm_getaddr error:");
    }

    total = (int *)addr;                                //将addr得值给名为total得整形指针，它用与访问共享内存中存储得整数值
    node_arr = (struct std_node *)(addr + sizeof(int)); //声明了一个struct std_node类型得指针node_arr，并将其赋值给addr+一个整数得大小

    //初始化共享内存
    while (1)
    {
        modbus_read_registers(mod, 0, 5, s5);
        printf("s5[0] = %d\n", s5[0]);
        printf("s5[1] = %d\n", s5[1]);
        printf("s5[2] = %d\n", s5[2]);
        printf("s5[3] = %d\n", s5[3]);
        printf("s5[4] = %d\n", s5[4]);
        modbus_read_bits(mod, 0, 9, data1);
        printf("data1[0] = %d\n", data1[0]);
        printf("data1[1] = %d\n", data1[1]);
        printf("data1[2] = %d\n", data1[2]);
        printf("data1[3] = %d\n", data1[3]);
        printf("data1[4] = %d\n", data1[4]);
        printf("data1[5] = %d\n", data1[5]);
        printf("data1[6] = %d\n", data1[6]);
        printf("data1[7] = %d\n", data1[7]);
        printf("data1[8] = %d\n", data1[8]); //疯鸣器报警

        for (int i = 0; i < *total; i++)
        {
            printf("total = %d\n", *total);
            if (node_arr[i].key == 5) //病人数量
            {
                node_arr[i].new_val.f_val = s5[0];
                node_arr[i].ret = 1;
                printf("病人数量读取成功：%.0f\n", node_arr[i].new_val.f_val);
            }
            else if (node_arr[i].key == 6) //药柜光照
            {
                node_arr[i].new_val.f_val = s5[1];
                printf("药柜光照读取成功：%.2f\n", node_arr[i].new_val.f_val);
                node_arr[i].ret = 1;
            }
            else if (node_arr[i].key == 7) //重量传感器
            {
                node_arr[i].new_val.f_val = s5[2];
                printf("重量传感器读取成功%.2f\n", node_arr[i].new_val.f_val);
                node_arr[i].ret = 1;
            }
            else if (node_arr[i].key == 8) //病房窗帘
            {
                node_arr[i].new_val.b_val = data1[0];
                printf("窗帘开关读取成功：%d\n", node_arr[i].new_val.b_val);
            }
            else if (node_arr[i].key == 9) //病房灯开关
            {
                node_arr[i].new_val.b_val = data1[1];
                printf("病房灯开关读取成功：%d\n", node_arr[i].new_val.b_val);
            }
            else if (node_arr[i].key == 10) //病房呼吸机（开/关）
            {
                node_arr[i].new_val.b_val = data1[2];
                printf("呼吸机开关读取成功：%d\n", node_arr[i].new_val.b_val);
            }
            else if (node_arr[i].key == 11) //病房监测仪（开/关）
            {
                node_arr[i].new_val.b_val = data1[3];
                printf("监测仪开关读取成功：%d\n", node_arr[i].new_val.b_val);
            }
            else if (node_arr[i].key == 12) //药柜的灯（开/关）
            {
                node_arr[i].new_val.b_val = data1[4];
                printf("药柜灯开关读取成功：%d\n", node_arr[i].new_val.b_val);
            }
            else if (node_arr[i].key == 13) //药柜制热（开/关）
            {
                node_arr[i].new_val.b_val = data1[5];
                printf("药柜制热开关读取成功：%d\n", node_arr[i].new_val.b_val);
            }
            else if (node_arr[i].key == 14) //药柜制冷（开/关）
            {
                node_arr[i].new_val.b_val = data1[6];
                printf("药柜制冷开关读取成功：%d\n", node_arr[i].new_val.b_val);
            }
            else if (node_arr[i].key == 15) //药柜除湿（开/关）
            {
                node_arr[i].new_val.b_val = data1[7];
                printf("药柜除湿开关读取成功：%d\n", node_arr[i].new_val.b_val);
            }
            else if (node_arr[i].key == 16) //蜂鸣器报警（开/关）
            {
                node_arr[i].new_val.b_val = data1[8];
                printf("蜂鸣器报警读取成功：%d\n", node_arr[i].new_val.b_val);
            }
            else if (node_arr[i].key == 17) //柜内温度
            {
                node_arr[i].new_val.f_val = s5[3];
                printf("柜内温度读取成功%.2f\n", node_arr[i].new_val.f_val);
                node_arr[i].ret = 1;
            }
            else if (node_arr[i].key == 18) //柜内湿度
            {
                node_arr[i].new_val.f_val = s5[4];
                printf("柜内湿度读取成功%.2f\n", node_arr[i].new_val.f_val);
                node_arr[i].ret = 1;
            }
        }

        sleep(1);
    }
}

void *Get_t(void *arg)
{
    printf("进入接收线程\n");
    struct msgbuf recv_buf;
    while (1)
    {
        printf("准备接收\n");
        if (msg_queue_recv("topic", &recv_buf, sizeof(recv_buf), 2, 0) > 0)
        {
            printf("接收2成功\n");
            cJSON *root = cJSON_Parse(recv_buf.mdata);
            printf("获取root成功\n");
            cJSON *item_key = cJSON_GetObjectItem(root, "key");
            printf("获取key成功\n");
            cJSON *item_val = cJSON_GetObjectItem(root, "val");
            printf("获取val成功\n");
            printf("接受到消息队列:\nkey = %d,val = %d\n", item_key->valueint, item_val->valueint);

            for (int i = 8; i <= 16; i++)
            {
                if (item_key->valueint == i)
                {
                    modbus_write_bit(mod, i - 8, item_val->valueint);
                    printf("更改了窗帘状态:%d\n", item_val->valueint);
                }
                else if (item_key->valueint == i)
                {
                    modbus_write_bit(mod, i - 8, item_val->valueint);
                    printf("更改了病房灯状态:%d\n", item_val->valueint);
                }
                else if (item_key->valueint == i)
                {
                    modbus_write_bit(mod, i - 8, item_val->valueint);
                    printf("更改了病房呼吸机状态:%d\n", item_val->valueint);
                }
                else if (item_key->valueint == i)
                {
                    modbus_write_bit(mod, i - 8, item_val->valueint);
                    printf("更改了病房监测仪状态:%d\n", item_val->valueint);
                }
            }
            cJSON_Delete(root);
        }
    }
}

void *Get_cloud(void *arg)
{
    printf("进入接收线程\n");
    struct msgbuf recv_buf;
    while (1)
    {
        if (msg_queue_recv("topic", &recv_buf, sizeof(recv_buf), 3, 0) > 0)
        {
            printf("接收3成功\n");
            cJSON *root = cJSON_Parse(recv_buf.mdata);
            printf("获取root成功\n");
            cJSON *item_key = cJSON_GetObjectItem(root, "key");
            printf("获取key成功\n");
            cJSON *item_val = cJSON_GetObjectItem(root, "val");
            printf("获取val成功\n");
            printf("接受到消息队列:\nkey = %d,val = %d\n", item_key->valueint, item_val->valueint);

            for (int i = 12; i <= 16; i++)
            {
                if (item_key->valueint == i) //药柜灯开关
                {
                    modbus_write_bit(mod, i - 8, item_val->valueint);
                    printf("更改了药柜灯开关状态:%d\n", item_val->valueint);
                }
                else if (item_key->valueint == i) //药柜制热
                {
                    modbus_write_bit(mod, i - 8, item_val->valueint);
                    printf("更改了药柜制热状态:%d\n", item_val->valueint);
                }
                else if (item_key->valueint == i) //药柜制冷
                {
                    modbus_write_bit(mod, i - 8, item_val->valueint);
                    printf("更改了药柜制冷状态:%d\n", item_val->valueint);
                }
                else if (item_key->valueint == i) //药柜除湿
                {
                    modbus_write_bit(mod, i - 8, item_val->valueint);
                    printf("更改了药柜除湿状态:%d\n", item_val->valueint);
                }
                else if (item_key->valueint == i) //疯鸣器开关
                {
                    modbus_write_bit(mod, i - 8, item_val->valueint);
                    printf("更改了疯鸣器开关状态:%d\n", item_val->valueint);
                }
            }
            cJSON_Delete(root);
        }
    }
}
int main(int argc, char const *argv[])
{

    //打开文件
    FILE *fd = fopen("JSONdata.json", "r+");
    if (fd == NULL)
    {
        printf("fopen err\n");
    }
    char buf[2048] = {};

    if (fread(buf, 1, 2048, fd) < 0)
    {
        perror("fread err");
        return -1;
    }

    cJSON *root = cJSON_Parse(buf);
    if (NULL == root)
    {
        perror("parse err\n");
        return -1;
    }

    char *version = cJSON_GetObjectItem(root, "version")->valuestring;
    cJSON *item = cJSON_GetObjectItem(root, "report");
    int type = cJSON_GetObjectItem(item, "type")->valueint;
    int period = cJSON_GetObjectItem(item, "period")->valueint;

    printf("version:%s\ntype:%d\nperiod:%d\n", version, type, period);

    //创建modbus上的子数干
    item = cJSON_GetObjectItem(root, "mb_dev");
    //获取服务器的地址ip
    cJSON *Ip = cJSON_GetObjectItem(item, "addr");
    //获取服务器的端口号
    cJSON *port = cJSON_GetObjectItem(item, "port");
    //打印sleva设备信息
    printf("ip:%s port:%d\n", Ip->valuestring, port->valueint);

    //以TCP的方式创建实例并且进行链接
    mod = modbus_new_tcp(Ip->valuestring, port->valueint); //电脑ip，端口号
    if (NULL == mod)
    {
        perror("mod err");
        return -1;
    }
    //设置主机IP
    int modslave = modbus_set_slave(mod, 1);
    if (modslave != 0)
    {
        perror("slr");
        return -1;
    }
    //设置和主机连接
    int modconnect = modbus_connect(mod);
    if (modconnect != 0)
    {
        perror("slave2 err");
        return -1;
    }

    //创建数据采集上传共享内存线程
    pthread_t tid1;
    if (pthread_create(&tid1, NULL, Data_get, mod))
    {
        perror("create err");
        return -1;
    }

    //创建指令处理的线程
    pthread_t tid2;
    if (pthread_create(&tid2, NULL, Get_t, mod))
    {
        perror("create err");
        return -1;
    }

    pthread_t tid3;
    if (pthread_create(&tid3, NULL, Get_cloud, mod))
    {
        perror("create err");
        return -1;
    }

    //线程回收
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    //关闭套接字
    modbus_close(mod);
    //释放空间
    free(mod);
    return 0;
}